<template>
  <div class="x-table-container">
    <slot :tableBtns="tableBtnsAdvance" :btnJustify="btnJustifyContent" name="table-btns">
      <div class="x-table-btn-container" :style="{'justify-content':btnJustifyContent}">
        <template v-for="(item,index) in tableBtnsAdvance">
          <slot
            :index="index"
            :icon="item.icon"
            :type="item.type"
            :show="item.show"
            :primaryId="item.primaryId"
            :name="item.name"
            :func="item.func"
            :disabled="item.disabled"
            :text="item.text"
          >
            <a-button
              v-if="item.show"
              :key="index"
              style="margin: 0 8px;"
              v-bind="item"
              @click="item.func"
            >
              {{ item.text }}
            </a-button>
          </slot>
        </template>
      </div>
    </slot>
    <slot
      :tableProps="tableProps"
      :columns="columns"
      :dataSource="currentDataSource"
      :loading="loading"
      :rowSelection="rowSelection"
      :scroll="scroll"
    >
      <a-table
        v-bind="tableProps"
        :columns="activeTableColumns"
        :data-source="currentDataSource"
        :loading="loading"
        :pagination="false"
        :row-selection="rowSelection"
        :scroll="scroll"
        @change="tableChangeHandler"
      >
        <template slot="customRender" slot-scope="text, record, index, column">
          <slot :name="column.dataIndex" v-bind="{ text, record, index, column }">
            <span :title="columnTextPostProcess(column, text, index)">
               {{ columnTextPostProcess(column, text, index) }}
            </span>
          </slot>
        </template>
      </a-table>
    </slot>
    <slot :pagination="pagination" :pageJustify="pageJustifyContent" name="table-page">
      <div v-if="showPage" class="x-table-page-container" :style="{'justifyContent':pageJustifyContent}">
        <a-pagination
          :current="pagination.current"
          :total="pagination.total"
          show-size-changer
          :page-size-options="paginationPageSizeOptions"
          :show-total="total => `共${total}条数据`"
          :page-size="pagination.pageSize"
          @change="pageChangeHandler"
          @showSizeChange="pageChangeHandler"
        >
          <template slot="buildOptionText" slot-scope="props">
            <span>{{ props.value }} 条/页</span>
          </template>
        </a-pagination>
      </div>
    </slot>
  </div>
</template>

<script>
import {cloneDeep} from 'lodash'

import {COMPONENT_TYPE, CUSTOM_EVENT_TYPE} from '../../constants'

export default {
  name: COMPONENT_TYPE.TABLE,
  provide() {
    return {
      xRenderTable: this
    }
  },
  props: {
    // 列配置
    columns: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 表格属性
    tableProps: {
      type: Object,
      default: () => {
        return {}
      }
    },
    // 按钮
    tableBtns: {
      type: Array,
      default: () => {
        return []
      }
    },
    // 数据
    dataSource: {
      type: Array,
      default: () => {
        return []
      }
    },
    loading: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      // 表格loading状态
      // 表格分页配置
      pagination: {
        // 当前页
        current: 1,
        // 当前页的数据个数
        pageSize: 10,
        // 数据格式配置
        pageSizeOptions: ['10', '20', '30', '40'],
        // 数据总数量
        total: 0
      },
      selectedRowKeys: []
    }
  },
  computed: {
    activeTableColumns: {
      get() {
        const {columns} = this
        const options = cloneDeep(columns || [])
        for (const option of options) {

          const {key, width, fixed, dataIndex, isGroup} = option
          if (!isGroup) {
            if (!key) {
              option.key = dataIndex
            }
            option.width = (dataIndex === 'index' ? 60 : (width || 100))

            if (!fixed || fixed !== 'right' && fixed !== 'left') {
              option.fixed = false
            }
          }

          // 插槽内容
          option['scopedSlots'] = {
            customRender: 'customRender'
          }
        }
        return options
      }
    },
    rowSelection: {
      get() {
        const {tableProps, selectedRowKeys, tableRowSelectedHandler} = this
        const {isSelect, selectIsFixed, selectType} = tableProps
        const config = {
          columnWidth: '50px',
          fixed: !!selectIsFixed,
          selectedRowKeys: selectedRowKeys,
          type: selectType || 'checkbox',
          onChange: tableRowSelectedHandler
        }
        return isSelect ? config : null
      }
    },
    showPage: {
      get() {
        const {tableProps} = this
        const {page} = tableProps || {}
        return !!page
      }
    },
    paginationPageSizeOptions: {
      get() {
        const {pagination} = this
        const {pageSizeOptions} = pagination || {}
        if (pageSizeOptions instanceof Array) {
          return pageSizeOptions
        }
        if (typeof (pageSizeOptions) === 'string') {
          return (new Function('return ' + pageSizeOptions))()
        }
        return []
      }
    },
    scroll: {
      get() {
        const {tableProps} = this
        const {scroll} = tableProps || {}
        return {
          ...(scroll ? (typeof (scroll) === 'string' ? (new Function('return ' + scroll))() : scroll) : {
            x: 'calc( 100vw )',
            y: 'calc( 100vh )'
          }),
          scrollToFirstRowOnChange: true
        }
      }
    },
    rowKey: {
      get() {
        const {tableProps} = this
        const {rowKey} = tableProps || {}
        return rowKey || 'id'
      }
    },
    pageJustifyContent: {
      get() {
        const {tableProps} = this
        const {pageJustifyContent} = tableProps || {}
        return pageJustifyContent || 'flex-end'
      }
    },
    btnJustifyContent: {
      get() {
        const {tableProps} = this
        const {btnJustifyContent} = tableProps || {}
        return btnJustifyContent || 'flex-start'
      }
    },
    currentDataSource: {
      get() {
        const {rowKey, dataSource, pagination} = this
        const arr = []
        let index = 0
        const key = rowKey
        for (const ds of dataSource) {
          const tmp = cloneDeep(ds)
          if (!tmp[key]) {
            tmp[key] = index++
          }
          arr.push(tmp)
        }
        return arr
      }
    },
    // 排序后的表格按钮
    tableBtnsAdvance: {
      get() {
        const {tableBtns: selfTableBtns, selectedRowKeys, currentDataSource} = this
        // 先进行排序
        const tableBtns = cloneDeep(selfTableBtns).sort((a, b) => a.sort - b.sort)
        for (let i = 0; i < tableBtns.length; i++) {
          const item = tableBtns[i]
          // 如果shape为 - 则删除属性
          if (item.shape === '-') {
            delete item.shape
          }

          item.func = () => {
            this.$emit(CUSTOM_EVENT_TYPE.CUSTOM_EVENT, {
              type: CUSTOM_EVENT_TYPE.BTN_EVENT,
              id: item.primaryId,
              name: item.name,
              text: item.text,
              selectedRowKeys,
              dataSource: currentDataSource
            })
          }
        }
        return tableBtns.sort((a, b) => a.sort - b.sort)
      }
    }
  },
  methods: {
    // //////////////////用户可以使用的方法 【begin】///////////////////////////////
    /**
     * 更改分页信息
     *
     * @param current 当前页
     * @param pageSize 一页条数
     * @param pageSizeOptions 分页参数
     * @param total 总数
     */
    changePage({current, pageSize, pageSizeOptions, total}) {
      this.pagePostProcess({current, pageSize, pageSizeOptions, total})
    },
    /**
     * 添加选中的数据
     *
     * @param selectedKeys 选中的数据
     */
    addSelectedKeys(selectedKeys = []) {
      this.selectedRowKeys.splice(this.selectedRowKeys.length + 1, 0, ...selectedKeys)
    },
    // //////////////////用户可以使用的方法 【end】///////////////////////////////

    /**
     * 表格数据选中事件
     *
     * @param selectedKeys 选中的key
     * @param selectedRows 选中的行数据
     */
    tableRowSelectedHandler(selectedKeys, selectedRows) {
      const {selectedRowKeys} = this
      const length = selectedRowKeys.length
      selectedRowKeys.splice(0, length, ...selectedKeys)
      if (selectedRowKeys.length !== 0) {
        this.$emit(CUSTOM_EVENT_TYPE.TABLE_SELECTED, {
          selectedRowKeys: selectedRowKeys,
          selectedData: selectedRows,
          instance: this
        })
      }
    },
    /**
     * table 发生变化事件
     *
     * @param pagination 分页数据
     * @param filters
     * @param sorter
     * @param currentDataSource 数据源
     */
    tableChangeHandler(pagination, filters, sorter, {currentDataSource}) {
      this.$emit(CUSTOM_EVENT_TYPE.TABLE_CHANGE, {
        pagination,
        filters,
        sorter,
        dataSource: currentDataSource,
        instance: this
      })
    },
    /**
     * 分页发生变化
     * @param current 当前页
     * @param pageSize 当前数据
     */
    pageChangeHandler(current, pageSize) {
      const {pagination} = this
      pagination.current = current
      pagination.pageSize = pageSize
      this.$emit(CUSTOM_EVENT_TYPE.TABLE_PAGE_CHANGE, {
        current,
        pageSize,
        instance: this
      })
    },
    /**
     * 分页处理
     */
    pagePostProcess({current, pageSize, pageSizeOptions, total}) {
      const {pagination} = this
      const paginationTmp = {
        current: current || 1,
        pageSize: pageSize || 10,
        pageSizeOptions: pageSizeOptions || ['10', '20', '30', '40'],
        total: total || 0
      }
      for (const key in paginationTmp) {
        this.$set(pagination, key, paginationTmp[key])
      }
    },
    /**
     * 获取列内容处理
     */
    columnTextPostProcess(column, text, index) {
      const {pagination} = this
      return column.dataIndex === 'index' ? (pagination.current - 1) * pagination.pageSize + index + 1 : text
    }
  },
  created() {
    // 初始化分页数据
    const {tableProps} = this
    const {pagination} = tableProps || {}
    const propPage = pagination ? (typeof (pagination) === 'string' ? (new Function('return ' + pagination))() : pagination) : {}
    this.pagePostProcess(propPage)
  }
}
</script>

<style scoped lang="css">
.x-table-container {
  margin-top: 8px;
  overflow: hidden;
  width: 100%;
  max-width: 100%;
  display: flex;
  flex-flow: column nowrap;
}

.x-table-page-container {
  width: 100%;
  display: flex;
  flex-flow: row nowrap;
  justify-content: flex-start;
  margin-top: 10px;
}

.x-table-btn-container {
  width: 100%;
  display: flex;
  flex-flow: row nowrap;
  margin: 8px 0;
}

/deep/ .ant-table-tbody > tr:nth-child(even) {
  background-color: #f8f8fa;
}
</style>
